#include "board.h"

/**********************************************定时器初始化及其相关中断函数 开始**********************************************/
volatile uint32_t timerFlag; // 获取定时器的中断标志位 用于测试

uint8_t Tim_Total_Flag;

/**
 * @brief 定时器0中断，1ms进入一次
 *
 */
void TIMER0_IRQHandler(void)
{
    static uint16_t Tim_Total_Pos;
    if (TimerIntStatus(TIMER0_BASE, true) == TIMER_TIMA_TIMEOUT)
    {
        if (++Tim_Total_Pos == 1000)
            Tim_Total_Pos = 0;
        if (Tim_Total_Pos % 49 == 0)
            Tim_Total_Flag = 2;
        if (Tim_Total_Pos % 9 == 0)
        {
            Tim_Total_Flag = 1;
            Pid_ServosAngleCtrl();
        }
        TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    }
}

/**
 * @brief TIMER0_Init  16/32级联成32
 * 配置系统定时外设
 * 配置定时器的模式，不拆分进行级联
 * 配置定时器的重装载值
 * 注册并开启中断
 */
void TIMER0_Init(void)
{
    // 使能定时器外设，对于其他函数也是，如果在级联的情况下还需要选择，那默认为选择TIMER_A
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // 将定时器AB级联在一起,不拆分
    // 配置定时器模式，将定时器拆分并采用连续加计数
    ROM_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);             // 如果需要拆分就要或上TIMER_CFG_SPLIT_PAIR
    ROM_TimerLoadSet(TIMER0_BASE, TIMER_BOTH, SysCtlClockGet() / 1000); // 重装载值为80M/0.8M，那么最后的频率为100hz
    // 注册定时器中断函数
    TimerIntRegister(TIMER0_BASE, TIMER_BOTH, TIMER0_IRQHandler);
    // 使能定时器的超时中断，
    ROM_TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    // 设置中断优先级
    ROM_IntPrioritySet(INT_TIMER0A, 0);
    // 使能中断
    ROM_IntEnable(INT_TIMER0A);
    // 启用处理器中断,单个中断从控制器门控到处理器。
    ROM_IntMasterEnable();
    // 启动定时器
    ROM_TimerEnable(TIMER0_BASE, TIMER_BOTH);
}
/**********************************************定时器初始化及其相关中断函数 结束**********************************************/

/**********************************************GPIO初始化及其相关中断函数 开始**********************************************/
/**
 * @brief gpio的配置
 *
 * 配置使能gpio端口
 * 配置gpid的方向为输入
 * 配置gpio的参数
 */

void GPIO_Init(void)
{

    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // 使能GPIOF口,五向按键
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK); // 使能GPIOK口,五向按键
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOJ); // 使能GPIOJ口,蜂鸣器

    /*配置引脚输入，五向按键

        可以通过GPIODirModeSet(),配置gpio为输入还是输出
        可以通过GPIOPadConfigSet()，配置gpio的驱动电流和输出模式（推挽，上/下拉）
        可以通过根据GPIOPinTypeGPIOInput默认设置gpio口，起始也是调用上面的函数

        GPIO_STRENGTH_2MA   驱动电流2ma
        GPIO_PIN_TYPE_STD_WPU   gpio设置为弱上拉
    */
    ROM_GPIODirModeSet(FButton_PORT_BASE_1, FButton_Up, GPIO_DIR_MODE_IN);
    ROM_GPIOPadConfigSet(FButton_PORT_BASE_1, FButton_Up, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    ROM_GPIODirModeSet(FButton_PORT_BASE_2, FButton_Middle, GPIO_DIR_MODE_IN);
    ROM_GPIODirModeSet(FButton_PORT_BASE_2, FButton_Down, GPIO_DIR_MODE_IN);
    ROM_GPIODirModeSet(FButton_PORT_BASE_2, FButton_Left, GPIO_DIR_MODE_IN);
    ROM_GPIODirModeSet(FButton_PORT_BASE_2, FButton_Right, GPIO_DIR_MODE_IN);

    ROM_GPIOPadConfigSet(FButton_PORT_BASE_2, FButton_Middle, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    ROM_GPIOPadConfigSet(FButton_PORT_BASE_2, FButton_Down, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    ROM_GPIOPadConfigSet(FButton_PORT_BASE_2, FButton_Left, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);
    ROM_GPIOPadConfigSet(FButton_PORT_BASE_2, FButton_Right, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    // 蜂鸣器配置
    ROM_GPIODirModeSet(BEEP_PORT_BASE, BEEP_PIN, GPIO_DIR_MODE_OUT);
    ROM_GPIOPadConfigSet(BEEP_PORT_BASE, BEEP_PIN, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
    GPIOPinWrite(BEEP_PORT_BASE, BEEP_PIN, 0); // 上电先关闭蜂鸣器
}
/**********************************************GPIO初始化及其相关中断函数 结束**********************************************/

/**********************************************其他板载功能函数 开始**********************************************/
void Beep_Blink(void)
{
    GPIOPinWrite(BEEP_PORT_BASE, BEEP_PIN, BEEP_PIN);
    delay_ms(30);
    GPIOPinWrite(BEEP_PORT_BASE, BEEP_PIN, 0);
	delay_ms(30);
}

uint8_t Openmv_TraceBall_Split(_trace *Trace)
{
    // 使用 sscanf 函数解析数据
    if( (uint8_t)(sscanf(Serial_Buffer, "x=%hu y=%hu w=%hu h=%hu", &Trace->ball_x, &Trace->ball_y, &Trace->ball_w, &Trace->ball_h) == 4))
    {
        return 1;
    }
    else
    {    //如果拆分失败表示当前没有检测的小球或者数据有误，那就将数据清除，为下一次的检测做准备
        //同时也是为了清除数据，以免pid的微分系数一直自增
        Trace->ball_x = 0;
        Trace->ball_y = 0;
        Trace->ball_w = 0;
        Trace->ball_h = 0;
        return 0;
    }
}

/**********************************************其他板载功能函数 结束**********************************************/
